//#preprocess
package com.sound.ampache;

/* Copyright (c) 2010 Brian Kirkman <kirkman.brian@gmail.com>
*
* +------------------------------------------------------------------------+
* | This program is free software; you can redistribute it and/or          |
* | modify it under the terms of the GNU General Public License            |
* | as published by the Free Software Foundation; either version 3         |
* | of the License, or (at your option) any later version.                 |
* |                                                                        |
* | This program is distributed in the hope that it will be useful,        |
* | but WITHOUT ANY WARRANTY; without even the implied warranty of         |
* | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          |
* | GNU General Public License for more details.                           |
* |                                                                        |
* | You should have received a copy of the GNU General Public License      |
* | along with this program; if not, write to the Free Software            |
* | Foundation, Inc., 59 Temple Place - Suite 330,                         |
* | Boston, MA  02111-1307, USA.                                           |
* +------------------------------------------------------------------------+
*
* Special thanks to the following: 
* Kevin Purdy, author of Amdroid, for much of the code used in this project
* 
* Jorge Ramon, author of MiamiCoder blog, for many great BlackBerry examples
* published on his blog.
* 
* 
*/

import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.DrawStyle;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;

//#ifdef TOUCH_SCREEN
import net.rim.device.api.ui.TouchEvent;
//#endif

public class TimeLineField extends Field{
	private int width;
	private int height;
	
	private double timeLength=0;
	private double contentLength=0;
	private double buffered=0;
	private double bufferStartsAt=0;
	private double now=0;	
	private double seekCursor=0;
	private String status="";
	
	private boolean focused = false;
	private boolean seekMode = false;
	private boolean focusable = true;
	private boolean bufferVisible = true;
	
	
	private int timeBase;
	
	private TimeLineFieldListener listener;
	
	public TimeLineField(int width, int height, int timeBase){
		super(Field.FIELD_TOP|Field.FIELD_LEFT);
		setExtent(width, height);	
		this.width = width;
		this.height = height;		
		this.timeBase = timeBase;
	}
	
	public void addTimeLineFieldListener(TimeLineFieldListener listener){
		this.listener = listener;
	}
	
	public void removeTimeLineFieldListener(){
		this.listener = null;
	}
	
	
	public void setTimeLength(long length){
		this.timeLength = length;		
	}
	
	public void setContentLength(long length){
		this.contentLength = length;		
	}
	
	public void setBuffered(long bufferStartsAt, long len){
		this.buffered = len;
		this.bufferStartsAt = bufferStartsAt;		
	}
	
	public void setNow(long now){
		if(!seekMode){
			this.now = now;			
		}
	}
	
	protected void layout(int width, int height) {
		setExtent(this.width, this.height);			
	}

	protected void paintBackground(Graphics graphics) {
		super.paintBackground(graphics);			
		graphics.setColor(Color.BLACK);
		graphics.fillRect(0, 0, getWidth(), getHeight());
	}

	protected void paint(Graphics graphics) {
		setExtent(width, height);	
		// draw the base timeline;
		double timelineX = 0;
		double timelineY = 2;
		double timelineWidth = width;	
		double timelineHeight = 5;
		
		if(focused){
			graphics.setColor(Color.WHITE);
			graphics.drawRoundRect(round(timelineX), round(timelineY), round(timelineWidth), round(timelineHeight), 3, 3);
			graphics.setColor(Color.GRAY);		
			graphics.fillRoundRect(round(timelineX+1), round(timelineY+1), round(timelineWidth-2), round(timelineHeight-2), 3, 3);			
		} else{
			graphics.setColor(Color.BLACK);
			graphics.drawRoundRect(round(timelineX), round(timelineY), round(timelineWidth), round(timelineHeight), 3, 3);
			graphics.setColor(Color.GRAY);		
			graphics.fillRoundRect(round(timelineX+1), round(timelineY+1), round(timelineWidth-2), round(timelineHeight-2), 3, 3);
		}
		
		// draw the buffer
		double bufferX;
		if(contentLength>0)
			bufferX = (bufferStartsAt/contentLength)*width;
		else
			bufferX = 0;
		
		double bufferY = timelineY+1;		
		double bufferWidth = (buffered/contentLength)*width;
		double bufferHeight = timelineHeight-2;
		Font statusFont = Font.getDefault().derive(Font.PLAIN, 14);		
		if(bufferVisible){			
			graphics.setColor(Color.DARKORANGE);		
			graphics.fillRoundRect(round(bufferX), round(bufferY), round(bufferWidth), round(bufferHeight), 3, 3);
			graphics.setFont(statusFont);
			graphics.setColor(Color.WHITE);
			graphics.drawText(status, 0, 8, DrawStyle.TOP|DrawStyle.RIGHT, width);
		}

		//draw the current position marker
		double markerX;
		if(timeLength>0)
			markerX = (now/timeLength)*width+1;
		else
			markerX = 0;
		
		double markerY = timelineY;
		double markerWidth = 16;
		double markerHeight = timelineHeight;
		Font markerFont = Font.getDefault().derive(Font.ITALIC, 14);
		
		
		
		if(seekMode){
			markerX = ((seekCursor/timeLength)*width)+1;			
			graphics.setColor(Color.CADETBLUE);
			graphics.drawRoundRect(round(markerX), round(markerY), round(markerWidth), round(markerHeight), 2, 2);		
			graphics.fillRoundRect(round(markerX+1), round(markerY+1), round(markerWidth-2), round(markerHeight-2), 2, 2);
			graphics.setColor(Color.WHITE);
			graphics.setFont(markerFont);
			graphics.drawText(secondsToTime(seekCursor)+"/"+secondsToTime(timeLength), 10, round(timelineHeight-2+12), DrawStyle.LEFT|DrawStyle.VCENTER);			
		} else{
			graphics.setColor(Color.WHITE);
			graphics.drawRoundRect(round(markerX), round(markerY), round(markerWidth), round(markerHeight), 2, 2);
			graphics.fillRoundRect(round(markerX+1), round(markerY+1), round(markerWidth-2), round(markerHeight-2), 2, 2);
			graphics.setFont(markerFont);
			graphics.drawText(secondsToTime(now) +"/"+secondsToTime(timeLength), 10, round(timelineHeight-2+12), DrawStyle.LEFT|DrawStyle.VCENTER);
		}
		setExtent(width, height);			
	}
	
	private int round(double d){
		return (int)Math.ceil(d);
	}
	
	private String secondsToTime(double d){
		String minutes = Integer.toString((int)Math.floor(d/60));
		String seconds = Integer.toString((int)Math.floor(d%60));
		String m = null;
		String s = null;
		
		if (minutes.length() > 1) {
			m = minutes;
		} else {
			m = "0" + minutes;
		}
		
		if (seconds.length() > 1) {
			s = seconds;
		} else {
			s = "0" + seconds;
		}

		return m + ":" + s;
	}	
	

	protected void onFocus(int direction) {
		focused = true;
		super.onFocus(direction);
		invalidate();
	}

	protected void onUnfocus() {
		focused = false;
		super.onUnfocus();
		invalidate();
	}

	
	protected boolean navigationClick(int status, int time) {
		
		if(timeLength>0){
			if(!seekMode){
				seekMode = true;
				seekCursor = now;
			}
			else{
				seekMode = false;
				
				if(seekCursor>now+buffered || seekCursor<now)
					buffered = 0;
				else
					buffered = (buffered-(seekCursor-now));
				
				now = seekCursor;
				
				if(listener!=null)
					listener.seek((long)now);
			}
			invalidate();
		}
		
		return true;
		
	}

	//#ifndef TOUCH_SCREEN 
	protected boolean navigationMovement(int dx, int dy, int status, int time) {
		
		if(seekCursor>timeLength){
			seekCursor=timeLength;
			return true;
		}
		if(seekCursor<0){
			seekCursor=0;
			return true;
		}
		
		if(seekMode && timeLength>0){
			seekCursor += (dx+dy)*timeBase;
			invalidate();
			return true;
		}
		else 
			return false;
			
	}
	//#endif
	
	//#ifdef TOUCH_SCREEN
	protected boolean touchEvent(TouchEvent message){
		if(message.getEvent()==TouchEvent.MOVE){
			int dx = (int)(message.getX(1)*timeLength/width);
			int dy = 0;
			if(seekCursor>timeLength){
				seekCursor=timeLength;
				return true;
			}
			if(seekCursor<0){
				seekCursor=0;
				return true;
			}
			
			if(seekMode && timeLength>0){
				seekCursor = (dx+dy);
				invalidate();
				return true;
			}
		}
		return super.touchEvent(message);
	}
	//#endif
	
	


	public boolean isFocusable() {
		return focusable;
	}
	
	

	protected void drawFocus(Graphics graphics, boolean on) {
		setExtent(width, height);	
	}
	
	public void setFocusable(boolean value){
		focusable = value;
	}
	
	public void setBufferVisible(boolean value){
		bufferVisible = value;
	}
	
	public void setStatus(String status){
		this.status = status;		
	}
	
	public void update(){
		invalidate();
	}
	
	public void setWidth(int width){
		this.width = width;		
	}
	
	public void setHeight(int height){
		this.height= height;
	}
	
	
}
